home *** CD-ROM | disk | FTP | other *** search
- //
- // MiscTee.h -- An object which will pass a message on to any of the objects
- // connected to it. This is useful for splitting an action
- // message to multiple recipients or for allowing multiple
- // delegates to be connected to provide different services.
- //
- // Written by David Fedchenko. Copyright 1994 by David Fedchenko.
- // Version 1.1 All rights reserved.
- // Additions by Don Yacktman to remove warnings and avoid infinite loops.
- //
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the author
- // and its use is governed by the MiscKit license, found in the file
- // "LICENSE.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
-
- #import "MiscTee.h"
-
- typedef struct
- {
- // Object *idObject; // Using this would remove warnings _if_ isa were
- // not protected, but as things stand, we'll have to live with the
- // warnings. :-( That's what you get for "isa hacking"!
- //id idObject; // This is where we got warnings...original definition...
- struct objc_class *idObject; // This seems to work right...
- SEL selAction;
- } CONPAIR;
-
- @implementation MiscTee
-
- - init
- {
- [super init];
- inTee = NO;
- idConnections = [[Storage alloc] initCount:0 elementSize:sizeof(CONPAIR)
- description:@encode(CONPAIR)];
- return self;
- }
-
- - free
- {
- [idConnections free];
-
- return [super free];
- }
-
- - addConnection:anObject with:(SEL)anAction
- {
- CONPAIR cp;
- CONPAIR * pcp;
- int i;
-
- cp.idObject = anObject;
- cp.selAction = anAction;
-
- // replace the action if the object is already in the list
- for (i = 0; i < [idConnections count]; i++)
- {
- pcp = (CONPAIR *)[idConnections elementAt:i];
- if (pcp->idObject == anObject)
- {
- pcp->selAction = anAction;
- return self;
- }
- }
-
- // new connection
- [idConnections addElement:&cp];
-
- return self;
- }
-
- - removeConnection:anObject
- {
- CONPAIR * pcp;
- int i;
-
- for (i = 0; i < [idConnections count]; i++)
- {
- pcp = (CONPAIR *)[idConnections elementAt:i];
- if (pcp->idObject == anObject)
- {
- [idConnections removeElementAt:i];
- break;
- }
- }
-
- return self;
- }
-
- - ping:sender
- {
- int i;
- CONPAIR * pcp;
-
- if (inTee) return self;
- inTee = YES;
- for (i = 0; i < [idConnections count]; i++) {
- pcp = (CONPAIR *)[idConnections elementAt:i];
- if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
- pcp->idObject != sender && pcp->selAction) {
- [pcp->idObject perform:pcp->selAction with:sender];
- }
- }
- inTee = NO;
- return self;
- }
-
- - forward:(SEL)aSelector :(marg_list)argFrame
- {
- int i;
- CONPAIR * pcp;
- void * pv = nil;
- BOOL fSent = NO;
-
- if (inTee) return self;
- inTee = YES;
- for (i = 0; i < [idConnections count]; i++)
- {
- pcp = (CONPAIR *)[idConnections elementAt:i];
- if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
- [pcp->idObject respondsTo:aSelector])
- {
- pv = [pcp->idObject performv:aSelector :argFrame];
- fSent = YES;
- }
- }
-
- if (!fSent)
- {
- [self doesNotRecognize:aSelector];
- }
- inTee = NO;
-
- return (id)pv;
- }
-
- -(BOOL) respondsTo:(SEL)aSelector
- {
- int i;
- CONPAIR * pcp;
-
- if ([super respondsTo:aSelector])
- {
- return YES;
- }
-
- for (i = 0; i < [idConnections count]; i++)
- {
- pcp = (CONPAIR *)[idConnections elementAt:i];
- if (strcmp(pcp->idObject->isa->name, "FREED(id)") &&
- [pcp->idObject respondsTo:aSelector])
- {
- // don't worry about multiple positive responses
- return YES;
- }
- }
-
- return NO;
- }
-
- - read:(NXTypedStream *)stream
- {
- [super read:stream];
-
- idConnections = NXReadObject(stream);
- inTee = NO;
- return self;
- }
-
- - write:(NXTypedStream *)stream
- {
- [super write:stream];
-
- NXWriteObject(stream, idConnections);
-
- return self;
- }
-
- @end
-